package com.liunian.channelhandler.handler;

import com.liunian.compress.Compressor;
import com.liunian.compress.CompressorFactory;
import com.liunian.serialize.Serializer;
import com.liunian.serialize.SerializerFactory;
import com.liunian.transport.message.MessageFormatConstant;
import com.liunian.transport.message.WrpcRespose;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

/**
 * 基于长度字段的帧解码器
 */
@Slf4j
public class WrpcResponseDecoder extends LengthFieldBasedFrameDecoder {
    public WrpcResponseDecoder() {
        super(
                // 找到当前报文的总长度，截取报文，截取出来的报文我们可以去解析。
                // 最大帧长度，超过这个 maxFrameLength 值会直接丢弃。
                MessageFormatConstant.MAX_FRAME_LENGTH,
                // 长度字段的偏移量
                MessageFormatConstant.MAGIC.length + MessageFormatConstant.VERSION_LENGTH + MessageFormatConstant.HEADER_FIELD_LENGTH,
                // 长度的字段的长度
                MessageFormatConstant.FULL_FIELD_LENGTH,
                // todo:负载的适配长度
                -(MessageFormatConstant.MAGIC.length + MessageFormatConstant.VERSION_LENGTH + MessageFormatConstant.HEADER_FIELD_LENGTH + MessageFormatConstant.FULL_FIELD_LENGTH),
                0);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        Object decode = super.decode(ctx, in);
        if (decode instanceof ByteBuf) {
            ByteBuf byteBuf = (ByteBuf) decode;
            return decodeFrame(byteBuf);
        }
        return null;
    }

    private Object decodeFrame(ByteBuf byteBuf) {
        // 1、解析魔术值
        byte[] magic = new byte[MessageFormatConstant.MAGIC.length];
        byteBuf.readBytes(magic);
        // 检测魔术值是否匹配
        for (int i = 0; i < magic.length; i++) {
            if (magic[i] != MessageFormatConstant.MAGIC[i]) {
                throw new RuntimeException("获得的请求不合法。");
            }
        }

        // 2、解析版本号
        byte version = byteBuf.readByte();
        if (version > MessageFormatConstant.VERSION) {
            throw new RuntimeException("获得的请求版本不被支持。");
        }

        // 3、解析头部长度
        short headLength = byteBuf.readShort();

        // 4、解析总长度
        int fullLength = byteBuf.readInt();

        // 5、响应码
        byte responseCode = byteBuf.readByte();

        // 6、解析序列化类型
        byte serializeType = byteBuf.readByte();

        // 7、解析压缩类型
        byte compressType = byteBuf.readByte();

        // 8、解析请求的id
        long requestId = byteBuf.readLong();

        // 9、时间戳
        long timeStamp = byteBuf.readLong();

        // 我们需要封装一个wrpcRequest
        WrpcRespose wrpcRespose = new WrpcRespose();
        wrpcRespose.setCode(responseCode);
        wrpcRespose.setCompressType(compressType);
        wrpcRespose.setSerializeType(serializeType);
        wrpcRespose.setRequestId(requestId);
        wrpcRespose.setTimeStamp(timeStamp);

        // todo:如果是心跳请求没有负载，此处可以判断并直接返回。
//        if (requestType == RequestType.HEART_BEAT.getId()) {
//            return wrpcRequest;
//        }

        int bodyLength = fullLength - headLength;
        byte[] payload = new byte[bodyLength];
        byteBuf.readBytes(payload);

        if (payload.length >0) {
            // 有了字节数组之后就可以解压缩和反序列化了
            // 解压缩，
            Compressor compressor = CompressorFactory.getCompressor(compressType).getImpl();
            payload = compressor.deCompress(payload);

            // 反序列化。
            Serializer serializer = SerializerFactory.getSerializer(wrpcRespose.getSerializeType()).getImpl();
            Object body = serializer.deserialize(payload, Object.class);
            wrpcRespose.setBody(body);

        }

        if (log.isDebugEnabled()) {
            log.debug("响应[{}]已经在调用端完成解码工作。", wrpcRespose.getRequestId());
        }

        return wrpcRespose;
    }
}
